package com.socio.resources;

import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import oauth.signpost.OAuthConsumer;
import oauth.signpost.basic.DefaultOAuthConsumer;

import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.api.taskqueue.TaskOptions.Method;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.socio.behaviors.DAOBehavior;
import com.socio.behaviors.UserUDIDBehavior;
import com.socio.model.ClientUser;
import com.socio.model.Day;
import com.socio.model.Event;
import com.socio.model.User;
import com.socio.model.Event.EventType;
import com.socio.model.responses.TwitterUserUpdateResponse;
import com.socio.twitter.model.Tweet;
import com.socio.utils.SocioUtils;
import com.socio.utils.FieldAccessor.FieldAccessorField;

@Path("/twitter")
public class TwitterResource {

	private static final Gson gson = new Gson();
	private static final String TWITTER_CONSUMER_KEY = "CEGOnFaZ2wj6b7dlfDIfg";
	private static final String TWITTER_CONSUMER_SECRET = "jlJVVIGwzjGdxjnX9TJAnsBeMsfOggoyZpPUsOMrU";
	
	@SuppressWarnings("unchecked")
	@Path("/lasttweet")
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public String getLastTweet(@QueryParam("udid") @DefaultValue("") String udid) throws Exception {
		
		if(udid.isEmpty())
			return "done";
		DAOBehavior userDAO = new UserUDIDBehavior();
		Queue queue = QueueFactory.getDefaultQueue();
        TaskOptions taskOptions = TaskOptions.Builder.withUrl("/resources/twitter/latesttweets")
        	.param("udid", udid).method(Method.GET);
		
		// get user with udid, create user if they aren't already in the db
		User user = null;
		Object result = userDAO.read(udid, null);
        List<Object> userList = (List<Object>)result;
        if(!userList.isEmpty() && userList.get(0) != null)
        	user = (User)userList.get(0);
        else
        	return "done";
		
        String accessToken = user.getTwitterAccessToken();
        if(accessToken == null || accessToken.isEmpty())
        	return "done";
		String[] tokenSecret = accessToken.split("\\|");
		OAuthConsumer consumer = new DefaultOAuthConsumer(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);
		consumer.setTokenWithSecret(tokenSecret[0], tokenSecret[1]);
		
		// setup connection to URL
		URL url = new URL("http://api.twitter.com/statuses/user_timeline.json?count=1&trim_user=true&include_rts=true");
		HttpURLConnection conn = (HttpURLConnection)url.openConnection();
		try {
			conn.setConnectTimeout(60000);
			conn.setRequestMethod("GET");
			consumer.sign(conn);
			
			// get results from url
			Type listType = new TypeToken<List<Tweet>>() {}.getType();
			InputStreamReader streamReader = new InputStreamReader(conn.getInputStream());
			List<Tweet> tweets = gson.fromJson(streamReader, listType);
			
			// add task to queue
			long eta = SocioUtils.nextDayFromTime(System.currentTimeMillis());
			queue.add(taskOptions.param("id", tweets.get(0).getId())
					.taskName("getLatestTweetsFor" +udid+ "On" +eta)
					.etaMillis(eta));
		} catch (Exception e) {
			return "done";
		} finally {
			conn.disconnect();
		}
		
		return "done";
	}
	
	@SuppressWarnings("unchecked")
	@Path("/latesttweets")
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public String getTweetsSinceTweet(@QueryParam("udid") @DefaultValue("") String udid,
			@QueryParam("id") @DefaultValue("") String tweetId) throws Exception {
	
		if(udid.isEmpty())
			return "done";
		DAOBehavior userDAO = new UserUDIDBehavior();
		
		// get user with udid, create user if they aren't already in the db
		User user = null;
		Object result = userDAO.read(udid, null);
        List<Object> userList = (List<Object>)result;
        if(!userList.isEmpty() && userList.get(0) != null)
        	user = (User)userList.get(0);
        else
        	return "done";
		
		String[] tokenSecret = user.getTwitterAccessToken().split("\\|");
		OAuthConsumer consumer = new DefaultOAuthConsumer(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);
		consumer.setTokenWithSecret(tokenSecret[0], tokenSecret[1]);
		
		// setup connection to URL
		URL url = new URL("http://api.twitter.com/statuses/user_timeline.json?trim_user=true&include_rts=true&since_id="
				+tweetId);
		HttpURLConnection conn = (HttpURLConnection)url.openConnection();
		try {
			conn.setConnectTimeout(60000);
			conn.setRequestMethod("GET");
			consumer.sign(conn);
			
			// get results from url
			Type listType = new TypeToken<List<Tweet>>() {}.getType();
			InputStreamReader streamReader = new InputStreamReader(conn.getInputStream());
			List<Tweet> tweets = gson.fromJson(streamReader, listType);
			
			 // increment score for each update then add to days
			Day day = new Day(SocioUtils.getDayStartTime());
	        for(Tweet tweet : tweets) {
	        	Event event = new Event();
	        	event.setType(EventType.Twitter);
	        	event.setChange("Status: " +tweet.getId());
	        	day.getEvents().add(event);
	        	day.incrementQuickScore();
	        }
	        userDAO.update(udid, Arrays.asList(FieldAccessorField.UserDays), 
	        		Arrays.asList((Object)day), null);
			
		} catch (Exception e) {
			return "done";
		} finally {
			conn.disconnect();
		}
		
		return "done";
	}
	
	@Path("/user/update")
    @POST
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes(MediaType.APPLICATION_JSON)
	public String updateUser(String json) {
		
		// setup
		TwitterUserUpdateResponse response = new TwitterUserUpdateResponse(false);
        ClientUser updatedUser = gson.fromJson(json, ClientUser.class);
		DAOBehavior userDAO = new UserUDIDBehavior();
		
		// update user with nickname
        Object result = userDAO.update(updatedUser.getAndroidUDID(), Arrays.asList(FieldAccessorField.UserTwitterAccessToken),
        		Arrays.asList((Object)updatedUser.getTwitterAccessToken()), null);
        if(result != null) {
        	response.setSuccess(true);
        	response.getUsers().add(((User)result).getClientUser());
        }
        
        return gson.toJson(response);
	}
}
